Rollup merge of #136699 - joboet:netaddr_from_inner, r=cuviper

std: replace the `FromInner` implementation for addresses with private conversion functions

Having these implementation available crate-wide means that platforms not using sockets for their networking code have to stub out the libc definitions required to support them. This PR moves the conversions to private helper functions that are only available where actually needed.

I also fixed the signature of the function converting from a C socket address to a Rust one: taking a reference to a `sockaddr_storage` resulted in unsound usage inside  `LookupHost::next`, which could create a reference to a structure smaller than `sockaddr_storage`. Thus I've replaced the argument type with a pointer and made the function `unsafe`.
This commit is contained in:
Jacob Pratt 2025-02-12 20:09:59 -05:00 committed by GitHub
commit 4ce473ccba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 155 additions and 348 deletions

View File

@ -8,32 +8,3 @@ pub use core::net::IpAddr;
pub use core::net::Ipv6MulticastScope;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::net::{Ipv4Addr, Ipv6Addr};
use crate::sys::net::netc as c;
use crate::sys_common::{FromInner, IntoInner};
impl IntoInner<c::in_addr> for Ipv4Addr {
#[inline]
fn into_inner(self) -> c::in_addr {
// `s_addr` is stored as BE on all machines and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) }
}
}
impl FromInner<c::in_addr> for Ipv4Addr {
fn from_inner(addr: c::in_addr) -> Ipv4Addr {
Ipv4Addr::from(addr.s_addr.to_ne_bytes())
}
}
impl IntoInner<c::in6_addr> for Ipv6Addr {
fn into_inner(self) -> c::in6_addr {
c::in6_addr { s6_addr: self.octets() }
}
}
impl FromInner<c::in6_addr> for Ipv6Addr {
#[inline]
fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
Ipv6Addr::from(addr.s6_addr)
}
}

View File

@ -6,50 +6,8 @@ mod tests;
pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::sys::net::{LookupHost, netc as c};
use crate::sys_common::{FromInner, IntoInner};
use crate::{io, iter, mem, option, slice, vec};
impl FromInner<c::sockaddr_in> for SocketAddrV4 {
fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port))
}
}
impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
SocketAddrV6::new(
Ipv6Addr::from_inner(addr.sin6_addr),
u16::from_be(addr.sin6_port),
addr.sin6_flowinfo,
addr.sin6_scope_id,
)
}
}
impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
fn into_inner(self) -> c::sockaddr_in {
c::sockaddr_in {
sin_family: c::AF_INET as c::sa_family_t,
sin_port: self.port().to_be(),
sin_addr: self.ip().into_inner(),
..unsafe { mem::zeroed() }
}
}
}
impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
fn into_inner(self) -> c::sockaddr_in6 {
c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t,
sin6_port: self.port().to_be(),
sin6_addr: self.ip().into_inner(),
sin6_flowinfo: self.flowinfo(),
sin6_scope_id: self.scope_id(),
..unsafe { mem::zeroed() }
}
}
}
use crate::sys::net::LookupHost;
use crate::{io, iter, option, slice, vec};
/// A trait for objects which can be converted or resolved to one or more
/// [`SocketAddr`] values.

View File

@ -122,7 +122,7 @@ impl BorrowedFd<'_> {
/// Creates a new `OwnedFd` instance that shares the same underlying file
/// description as the existing `BorrowedFd` instance.
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?;
let fd = sys::net::cvt(unsafe { crate::sys::abi::sockets::dup(self.as_raw_fd()) })?;
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
}
@ -168,7 +168,7 @@ impl FromRawFd for OwnedFd {
impl Drop for OwnedFd {
#[inline]
fn drop(&mut self) {
unsafe { sys::net::netc::close(self.fd.as_inner()) };
unsafe { crate::sys::abi::sockets::close(self.fd.as_inner()) };
}
}

View File

@ -499,38 +499,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
LookupHost::new(format!("{host}:{port}"))
}
}
#[allow(bad_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -3,9 +3,9 @@ mod tests;
use crate::ffi::{c_int, c_void};
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::sys::common::small_c_string::run_with_cstr;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::sys_common::{AsInner, FromInner};
use crate::time::Duration;
use crate::{cmp, fmt, mem, ptr};
@ -79,6 +79,111 @@ cfg_if::cfg_if! {
}
}
////////////////////////////////////////////////////////////////////////////////
// address conversions
////////////////////////////////////////////////////////////////////////////////
fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr {
// `s_addr` is stored as BE on all machines and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) }
}
fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr {
c::in6_addr { s6_addr: addr.octets() }
}
fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr {
Ipv4Addr::from(addr.s_addr.to_ne_bytes())
}
fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr {
Ipv6Addr::from(addr.s6_addr)
}
fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in {
c::sockaddr_in {
sin_family: c::AF_INET as c::sa_family_t,
sin_port: addr.port().to_be(),
sin_addr: ip_v4_addr_to_c(addr.ip()),
..unsafe { mem::zeroed() }
}
}
fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 {
c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t,
sin6_port: addr.port().to_be(),
sin6_addr: ip_v6_addr_to_c(addr.ip()),
sin6_flowinfo: addr.flowinfo(),
sin6_scope_id: addr.scope_id(),
..unsafe { mem::zeroed() }
}
}
fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 {
SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port))
}
fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 {
SocketAddrV6::new(
ip_v6_addr_from_c(addr.sin6_addr),
u16::from_be(addr.sin6_port),
addr.sin6_flowinfo,
addr.sin6_scope_id,
)
}
/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
#[repr(C)]
union SocketAddrCRepr {
v4: c::sockaddr_in,
v6: c::sockaddr_in6,
}
impl SocketAddrCRepr {
fn as_ptr(&self) -> *const c::sockaddr {
self as *const _ as *const c::sockaddr
}
}
fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
match addr {
SocketAddr::V4(a) => {
let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) };
(sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
}
SocketAddr::V6(a) => {
let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) };
(sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
}
}
}
unsafe fn socket_addr_from_c(
storage: *const c::sockaddr_storage,
len: usize,
) -> io::Result<SocketAddr> {
match (*storage).ss_family as c_int {
c::AF_INET => {
assert!(len >= mem::size_of::<c::sockaddr_in>());
Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
*(storage as *const _ as *const c::sockaddr_in)
})))
}
c::AF_INET6 => {
assert!(len >= mem::size_of::<c::sockaddr_in6>());
Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
*(storage as *const _ as *const c::sockaddr_in6)
})))
}
_ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
}
}
////////////////////////////////////////////////////////////////////////////////
// sockaddr and misc bindings
////////////////////////////////////////////////////////////////////////////////
@ -124,25 +229,7 @@ where
let mut storage: c::sockaddr_storage = mem::zeroed();
let mut len = mem::size_of_val(&storage) as c::socklen_t;
cvt(f((&raw mut storage) as *mut _, &mut len))?;
sockaddr_to_addr(&storage, len as usize)
}
}
pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
match storage.ss_family as c_int {
c::AF_INET => {
assert!(len >= mem::size_of::<c::sockaddr_in>());
Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
*(storage as *const _ as *const c::sockaddr_in)
})))
}
c::AF_INET6 => {
assert!(len >= mem::size_of::<c::sockaddr_in6>());
Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
*(storage as *const _ as *const c::sockaddr_in6)
})))
}
_ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
socket_addr_from_c(&storage, len as usize)
}
}
@ -179,7 +266,7 @@ impl Iterator for LookupHost {
unsafe {
let cur = self.cur.as_ref()?;
self.cur = cur.ai_next;
match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) {
match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
Ok(addr) => return Some(addr),
Err(_) => continue,
}
@ -432,7 +519,7 @@ impl TcpListener {
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
// Bind our new socket
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
cfg_if::cfg_if! {
@ -473,7 +560,7 @@ impl TcpListener {
let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of_val(&storage) as c::socklen_t;
let sock = self.inner.accept((&raw mut storage) as *mut _, &mut len)?;
let addr = sockaddr_to_addr(&storage, len as usize)?;
let addr = unsafe { socket_addr_from_c(&storage, len as usize)? };
Ok((TcpStream { inner: sock }, addr))
}
@ -542,7 +629,7 @@ impl UdpSocket {
init();
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
Ok(UdpSocket { inner: sock })
}
@ -574,7 +661,7 @@ impl UdpSocket {
pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
let (dst, dstlen) = dst.into_inner();
let (dst, dstlen) = socket_addr_to_c(dst);
let ret = cvt(unsafe {
c::sendto(
self.inner.as_raw(),
@ -656,15 +743,15 @@ impl UdpSocket {
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = c::ip_mreq {
imr_multiaddr: multiaddr.into_inner(),
imr_interface: interface.into_inner(),
imr_multiaddr: ip_v4_addr_to_c(multiaddr),
imr_interface: ip_v4_addr_to_c(interface),
};
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
}
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: multiaddr.into_inner(),
ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
@ -672,15 +759,15 @@ impl UdpSocket {
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = c::ip_mreq {
imr_multiaddr: multiaddr.into_inner(),
imr_interface: interface.into_inner(),
imr_multiaddr: ip_v4_addr_to_c(multiaddr),
imr_interface: ip_v4_addr_to_c(interface),
};
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: multiaddr.into_inner(),
ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
@ -720,7 +807,7 @@ impl UdpSocket {
}
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
let (addr, len) = addr?.into_inner();
let (addr, len) = socket_addr_to_c(addr?);
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
}
}
@ -743,38 +830,3 @@ impl fmt::Debug for UdpSocket {
res.field(name, &self.inner.as_raw()).finish()
}
}
////////////////////////////////////////////////////////////////////////////////
// Converting SocketAddr to libc representation
////////////////////////////////////////////////////////////////////////////////
/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: c::sockaddr_in,
v6: c::sockaddr_in6,
}
impl SocketAddrCRepr {
pub fn as_ptr(&self) -> *const c::sockaddr {
self as *const _ as *const c::sockaddr
}
}
impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr {
fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) {
match *self {
SocketAddr::V4(ref a) => {
let sockaddr = SocketAddrCRepr { v4: a.into_inner() };
(sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
}
SocketAddr::V6(ref a) => {
let sockaddr = SocketAddrCRepr { v6: a.into_inner() };
(sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
}
}
}
}

View File

@ -2,13 +2,13 @@
use core::ffi::c_int;
pub(crate) use hermit_abi as netc;
pub(super) use hermit_abi as netc;
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
use crate::sys::fd::FileDesc;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys::time::Instant;
pub use crate::sys::{cvt, cvt_r};
use crate::sys_common::{AsInner, FromInner, IntoInner};
@ -55,7 +55,7 @@ impl Socket {
}
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(())
}
@ -63,7 +63,7 @@ impl Socket {
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?;
let r = unsafe {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len))
};
self.set_nonblocking(false)?;
@ -195,7 +195,7 @@ impl Socket {
&mut addrlen,
)
})?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -1,17 +1,17 @@
use libc::{c_int, c_void, size_t};
use self::netc::{MSG_PEEK, sockaddr, socklen_t};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
use crate::sys::abi;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys_common::{FromInner, IntoInner};
use crate::time::Duration;
use crate::{cmp, mem, ptr, str};
pub mod netc {
pub(super) mod netc {
pub use crate::sys::abi::sockets::*;
}
@ -131,7 +131,7 @@ impl Socket {
}
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(())
}
@ -256,7 +256,7 @@ impl Socket {
&mut addrlen,
)
})?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -5,7 +5,7 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys::net::{getsockopt, setsockopt};
use crate::sys::pal::IsMinusOne;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant};
@ -19,8 +19,9 @@ cfg_if::cfg_if! {
}
}
pub(crate) use libc as netc;
pub(super) use libc as netc;
use super::{socket_addr_from_c, socket_addr_to_c};
pub use crate::sys::{cvt, cvt_r};
#[expect(non_camel_case_types)]
@ -150,7 +151,7 @@ impl Socket {
}
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
loop {
let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) };
if result.is_minus_one() {
@ -168,7 +169,7 @@ impl Socket {
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?;
let r = unsafe {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len))
};
self.set_nonblocking(false)?;
@ -334,7 +335,7 @@ impl Socket {
&mut addrlen,
)
})?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -1,19 +1,18 @@
#![deny(unsafe_op_in_unsafe_fn)]
pub(super) use libc as netc;
use libc::{c_int, c_void, size_t};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys::unsupported;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant};
use crate::{cmp, mem, str};
pub extern crate libc as netc;
#[allow(non_camel_case_types)]
pub type wrlen_t = size_t;
@ -89,7 +88,7 @@ impl Socket {
}
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(())
}
@ -224,7 +223,7 @@ impl Socket {
&mut addrlen,
)
})?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -2,6 +2,7 @@
use core::ffi::{c_int, c_long, c_ulong, c_ushort};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read};
use crate::net::{Shutdown, SocketAddr};
use crate::os::windows::io::{
@ -16,7 +17,7 @@ use crate::{cmp, mem, ptr, sys};
#[allow(non_camel_case_types)]
pub type wrlen_t = i32;
pub mod netc {
pub(super) mod netc {
//! BSD socket compatibility shim
//!
//! Some Windows API types are not quite what's expected by our cross-platform
@ -225,7 +226,7 @@ impl Socket {
}
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner();
let (addr, len) = socket_addr_to_c(addr);
let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) };
cvt(result).map(drop)
}
@ -401,12 +402,12 @@ impl Socket {
let error = unsafe { c::WSAGetLastError() };
if error == c::WSAESHUTDOWN {
Ok((0, super::sockaddr_to_addr(&storage, addrlen as usize)?))
Ok((0, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} else {
Err(io::Error::from_raw_os_error(error))
}
}
_ => Ok((result as usize, super::sockaddr_to_addr(&storage, addrlen as usize)?)),
_ => Ok((result as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })),
}
}
@ -451,11 +452,11 @@ impl Socket {
}
None => 0,
};
super::setsockopt(self, c::SOL_SOCKET, kind, timeout)
setsockopt(self, c::SOL_SOCKET, kind, timeout)
}
pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> {
let raw: u32 = super::getsockopt(self, c::SOL_SOCKET, kind)?;
let raw: u32 = getsockopt(self, c::SOL_SOCKET, kind)?;
if raw == 0 {
Ok(None)
} else {
@ -488,26 +489,26 @@ impl Socket {
l_linger: linger.unwrap_or_default().as_secs() as c_ushort,
};
super::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
let val: c::LINGER = super::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
let val: c::LINGER = getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
super::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL)
setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL)
}
pub fn nodelay(&self) -> io::Result<bool> {
let raw: c::BOOL = super::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
let raw: c::BOOL = getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
Ok(raw != 0)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
let raw: c_int = super::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?;
let raw: c_int = getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?;
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
}

View File

@ -332,38 +332,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported()
}
}
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -332,38 +332,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported()
}
}
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -505,38 +505,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported()
}
}
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -46,38 +46,3 @@ pub struct GetAddress {
}
pub use dns::LookupHost;
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}