Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
168
vendor/mio/src/sys/unix/net.rs
vendored
Normal file
168
vendor/mio/src/sys/unix/net.rs
vendored
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
use std::io;
|
||||
use std::mem::size_of;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
|
||||
pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: libc::c_int) -> io::Result<libc::c_int> {
|
||||
let domain = match addr {
|
||||
SocketAddr::V4(..) => libc::AF_INET,
|
||||
SocketAddr::V6(..) => libc::AF_INET6,
|
||||
};
|
||||
|
||||
new_socket(domain, socket_type)
|
||||
}
|
||||
|
||||
/// Create a new non-blocking socket.
|
||||
pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::Result<libc::c_int> {
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
|
||||
|
||||
// Gives a warning for platforms without SOCK_NONBLOCK.
|
||||
#[allow(clippy::let_and_return)]
|
||||
let socket = syscall!(socket(domain, socket_type, 0));
|
||||
|
||||
// Mimick `libstd` and set `SO_NOSIGPIPE` on apple systems.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
let socket = socket.and_then(|socket| {
|
||||
syscall!(setsockopt(
|
||||
socket,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_NOSIGPIPE,
|
||||
&1 as *const libc::c_int as *const libc::c_void,
|
||||
size_of::<libc::c_int>() as libc::socklen_t
|
||||
))
|
||||
.map(|_| socket)
|
||||
});
|
||||
|
||||
// Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
let socket = socket.and_then(|socket| {
|
||||
// For platforms that don't support flags in socket, we need to
|
||||
// set the flags ourselves.
|
||||
syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))
|
||||
.and_then(|_| syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| socket))
|
||||
.map_err(|e| {
|
||||
// If either of the `fcntl` calls failed, ensure the socket is
|
||||
// closed and return the error.
|
||||
let _ = syscall!(close(socket));
|
||||
e
|
||||
})
|
||||
});
|
||||
|
||||
socket
|
||||
}
|
||||
|
||||
/// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level
|
||||
/// SocketAddr* types into their system representation. The benefit of this specific
|
||||
/// type over using `libc::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 cleaner from Rust.
|
||||
#[repr(C)]
|
||||
pub(crate) union SocketAddrCRepr {
|
||||
v4: libc::sockaddr_in,
|
||||
v6: libc::sockaddr_in6,
|
||||
}
|
||||
|
||||
impl SocketAddrCRepr {
|
||||
pub(crate) fn as_ptr(&self) -> *const libc::sockaddr {
|
||||
self as *const _ as *const libc::sockaddr
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a Rust `SocketAddr` into the system representation.
|
||||
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_t) {
|
||||
match addr {
|
||||
SocketAddr::V4(ref addr) => {
|
||||
// `s_addr` is stored as BE on all machine and the array is in BE order.
|
||||
// So the native endian conversion method is used so that it's never swapped.
|
||||
let sin_addr = libc::in_addr {
|
||||
s_addr: u32::from_ne_bytes(addr.ip().octets()),
|
||||
};
|
||||
|
||||
let sockaddr_in = libc::sockaddr_in {
|
||||
sin_family: libc::AF_INET as libc::sa_family_t,
|
||||
sin_port: addr.port().to_be(),
|
||||
sin_addr,
|
||||
sin_zero: [0; 8],
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
sin_len: 0,
|
||||
};
|
||||
|
||||
let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
|
||||
let socklen = size_of::<libc::sockaddr_in>() as libc::socklen_t;
|
||||
(sockaddr, socklen)
|
||||
}
|
||||
SocketAddr::V6(ref addr) => {
|
||||
let sockaddr_in6 = libc::sockaddr_in6 {
|
||||
sin6_family: libc::AF_INET6 as libc::sa_family_t,
|
||||
sin6_port: addr.port().to_be(),
|
||||
sin6_addr: libc::in6_addr {
|
||||
s6_addr: addr.ip().octets(),
|
||||
},
|
||||
sin6_flowinfo: addr.flowinfo(),
|
||||
sin6_scope_id: addr.scope_id(),
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
sin6_len: 0,
|
||||
#[cfg(target_os = "illumos")]
|
||||
__sin6_src_id: 0,
|
||||
};
|
||||
|
||||
let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
|
||||
let socklen = size_of::<libc::sockaddr_in6>() as libc::socklen_t;
|
||||
(sockaddr, socklen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `libc::sockaddr` compatible struct into a native Rust `SocketAddr`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `storage` must have the `ss_family` field correctly initialized.
|
||||
/// `storage` must be initialised to a `sockaddr_in` or `sockaddr_in6`.
|
||||
pub(crate) unsafe fn to_socket_addr(
|
||||
storage: *const libc::sockaddr_storage,
|
||||
) -> io::Result<SocketAddr> {
|
||||
match (*storage).ss_family as libc::c_int {
|
||||
libc::AF_INET => {
|
||||
// Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
|
||||
let addr: &libc::sockaddr_in = &*(storage as *const libc::sockaddr_in);
|
||||
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
|
||||
let port = u16::from_be(addr.sin_port);
|
||||
Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
|
||||
}
|
||||
libc::AF_INET6 => {
|
||||
// Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
|
||||
let addr: &libc::sockaddr_in6 = &*(storage as *const libc::sockaddr_in6);
|
||||
let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
|
||||
let port = u16::from_be(addr.sin6_port);
|
||||
Ok(SocketAddr::V6(SocketAddrV6::new(
|
||||
ip,
|
||||
port,
|
||||
addr.sin6_flowinfo,
|
||||
addr.sin6_scope_id,
|
||||
)))
|
||||
}
|
||||
_ => Err(io::ErrorKind::InvalidInput.into()),
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue