libc: partially sync ygglibc with socket changes
This commit is contained in:
parent
c2cf314dcd
commit
0105be8fea
@ -1,13 +1,30 @@
|
||||
use core::{ffi::{c_int, c_void}, mem::MaybeUninit, ptr::{null, null_mut}};
|
||||
use core::{
|
||||
ffi::{c_int, c_void},
|
||||
net::SocketAddr,
|
||||
ptr::{null, null_mut},
|
||||
};
|
||||
|
||||
use yggdrasil_abi::{
|
||||
abi_serde::wire,
|
||||
net::{MessageHeader, MessageHeaderMut},
|
||||
};
|
||||
use yggdrasil_rt::{io::RawFd, sys as syscall};
|
||||
|
||||
use crate::{error::{CIsizeResult, ResultExt, TryFromExt}, headers::{errno::Errno, sys_socket::SocketAddrExt}, util::PointerExt};
|
||||
use crate::{
|
||||
error::{CIsizeResult, ResultExt, TryFromExt},
|
||||
headers::errno::Errno,
|
||||
util::PointerExt,
|
||||
};
|
||||
|
||||
use super::{msghdr, sockaddr, socklen_t};
|
||||
use super::{msghdr, sockaddr, socklen_t, SocketAddrExt};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn recv(fd: c_int, buffer: *mut c_void, len: usize, flags: c_int) -> CIsizeResult {
|
||||
unsafe extern "C" fn recv(
|
||||
fd: c_int,
|
||||
buffer: *mut c_void,
|
||||
len: usize,
|
||||
flags: c_int,
|
||||
) -> CIsizeResult {
|
||||
recvfrom(fd, buffer, len, flags, null_mut(), null_mut())
|
||||
}
|
||||
|
||||
@ -21,12 +38,24 @@ unsafe extern "C" fn recvfrom(
|
||||
remote_len: *mut socklen_t,
|
||||
) -> CIsizeResult {
|
||||
let _ = flags;
|
||||
let buffer = buffer.cast::<u8>().ensure_slice_mut(len);
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let mut peer = MaybeUninit::uninit();
|
||||
let len = syscall::receive_from(fd, buffer, &mut peer).e_map_err(Errno::from)?;
|
||||
if !remote.is_null() && !remote_len.is_null() {
|
||||
let peer = peer.assume_init();
|
||||
let payload = buffer.cast::<u8>().ensure_slice_mut(len);
|
||||
let mut source = if remote.is_null() || remote_len.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some([0u8; 32])
|
||||
};
|
||||
let mut message = MessageHeaderMut {
|
||||
payload,
|
||||
source: source.as_mut().map(|x| &mut x[..]),
|
||||
ancillary: None,
|
||||
ancillary_len: 0,
|
||||
};
|
||||
let len = syscall::receive_message(fd, &mut message).e_map_err(Errno::from)?;
|
||||
if let Some(source) = source.as_ref() {
|
||||
let peer: SocketAddr = wire::from_slice(source)
|
||||
.map_err(yggdrasil_rt::Error::from)
|
||||
.e_map_err(Errno::from)?;
|
||||
*remote_len = peer.to_c(remote, *remote_len)?;
|
||||
}
|
||||
CIsizeResult::success(len)
|
||||
@ -41,7 +70,12 @@ unsafe extern "C" fn recvmsg(fd: c_int, message: *mut msghdr, flags: c_int) -> C
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn send(fd: c_int, data: *const c_void, len: usize, flags: c_int) -> CIsizeResult {
|
||||
unsafe extern "C" fn send(
|
||||
fd: c_int,
|
||||
data: *const c_void,
|
||||
len: usize,
|
||||
flags: c_int,
|
||||
) -> CIsizeResult {
|
||||
sendto(fd, data, len, flags, null(), 0)
|
||||
}
|
||||
|
||||
@ -64,12 +98,22 @@ unsafe extern "C" fn sendto(
|
||||
) -> CIsizeResult {
|
||||
let _ = flags;
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let data = data.cast::<u8>().ensure_slice(len);
|
||||
let peer = if !remote.is_null() && remote_len != 0 {
|
||||
Some(remote.to_rust(remote_len)?)
|
||||
let payload = data.cast::<u8>().ensure_slice(len);
|
||||
let destination = if remote.is_null() || remote_len == 0 {
|
||||
let mut sockaddr_buf = [0; 32];
|
||||
let sockaddr = remote.to_rust(len)?;
|
||||
wire::to_slice(&sockaddr, &mut sockaddr_buf)
|
||||
.map_err(yggdrasil_rt::Error::from)
|
||||
.e_map_err(Errno::from)?;
|
||||
Some(sockaddr_buf)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let len = syscall::send_to(fd, data, &peer).e_map_err(Errno::from)?;
|
||||
let message = MessageHeader {
|
||||
destination: destination.as_ref().map(|x| &x[..]),
|
||||
payload,
|
||||
ancillary: &[],
|
||||
};
|
||||
let len = syscall::send_message(fd, &message).e_map_err(Errno::from)?;
|
||||
CIsizeResult::success(len)
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ impl SocketAddrExt<sockaddr> for SocketAddr {
|
||||
match self {
|
||||
Self::V4(v4) if len >= size_of::<sockaddr_in>() => v4.to_c(storage.cast(), len),
|
||||
Self::V6(v6) if len >= size_of::<sockaddr_in6>() => v6.to_c(storage.cast(), len),
|
||||
_ => EResult::Err(Errno::EINVAL)
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,160 +1,151 @@
|
||||
use core::ffi::{c_int, c_void};
|
||||
|
||||
use yggdrasil_rt::{
|
||||
io::RawFd,
|
||||
net::{self as rt, options},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult, OptionExt, ResultExt, TryFromExt},
|
||||
headers::{
|
||||
errno::Errno,
|
||||
netinet_in::{IPPROTO_TCP, TCP_NODELAY},
|
||||
sys_socket::{SocketAddrExt, SOL_SOCKET, SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO},
|
||||
sys_time::timeval,
|
||||
},
|
||||
};
|
||||
use crate::error::CIntZeroResult;
|
||||
|
||||
use super::{sockaddr, socklen_t};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getsockopt(
|
||||
fd: c_int,
|
||||
level: c_int,
|
||||
name: c_int,
|
||||
value: *mut c_void,
|
||||
size: *mut socklen_t,
|
||||
_fd: c_int,
|
||||
_level: c_int,
|
||||
_name: c_int,
|
||||
_value: *mut c_void,
|
||||
_size: *mut socklen_t,
|
||||
) -> CIntZeroResult {
|
||||
if value.is_null() || size.is_null() {
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
todo!()
|
||||
// if value.is_null() || size.is_null() {
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
|
||||
let space = *size;
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
// let space = *size;
|
||||
// let fd = RawFd::e_try_from(fd)?;
|
||||
|
||||
*size = match (level, name) {
|
||||
(SOL_SOCKET, SO_RCVTIMEO) if space >= size_of::<timeval>() => {
|
||||
let timeout =
|
||||
rt::get_socket_option!(fd, options::RecvTimeout).e_map_err(Errno::from)?;
|
||||
let value = value.cast::<timeval>();
|
||||
match timeout {
|
||||
Some(timeout) => value.write(timeval::from(timeout)),
|
||||
None => value.write(timeval::zero()),
|
||||
}
|
||||
size_of::<timeval>()
|
||||
}
|
||||
(SOL_SOCKET, SO_SNDTIMEO) => {
|
||||
let timeout =
|
||||
rt::get_socket_option!(fd, options::SendTimeout).e_map_err(Errno::from)?;
|
||||
let value = value.cast::<timeval>();
|
||||
match timeout {
|
||||
Some(timeout) => value.write(timeval::from(timeout)),
|
||||
None => value.write(timeval::zero()),
|
||||
}
|
||||
size_of::<timeval>()
|
||||
}
|
||||
(SOL_SOCKET, SO_BROADCAST) => {
|
||||
let broadcast =
|
||||
rt::get_socket_option!(fd, options::Broadcast).e_map_err(Errno::from)?;
|
||||
let value = value.cast::<c_int>();
|
||||
value.write(broadcast as c_int);
|
||||
size_of::<c_int>()
|
||||
}
|
||||
(IPPROTO_TCP, TCP_NODELAY) => {
|
||||
let broadcast = rt::get_socket_option!(fd, options::NoDelay).e_map_err(Errno::from)?;
|
||||
let value = value.cast::<c_int>();
|
||||
value.write(broadcast as c_int);
|
||||
size_of::<c_int>()
|
||||
}
|
||||
_ => {
|
||||
yggdrasil_rt::debug_trace!("Unhandled getsockopt({level}, {name}, {space})");
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
};
|
||||
// *size = match (level, name) {
|
||||
// (SOL_SOCKET, SO_RCVTIMEO) if space >= size_of::<timeval>() => {
|
||||
// let timeout =
|
||||
// rt::get_socket_option!(fd, options::RecvTimeout).e_map_err(Errno::from)?;
|
||||
// let value = value.cast::<timeval>();
|
||||
// match timeout {
|
||||
// Some(timeout) => value.write(timeval::from(timeout)),
|
||||
// None => value.write(timeval::zero()),
|
||||
// }
|
||||
// size_of::<timeval>()
|
||||
// }
|
||||
// (SOL_SOCKET, SO_SNDTIMEO) => {
|
||||
// let timeout =
|
||||
// rt::get_socket_option!(fd, options::SendTimeout).e_map_err(Errno::from)?;
|
||||
// let value = value.cast::<timeval>();
|
||||
// match timeout {
|
||||
// Some(timeout) => value.write(timeval::from(timeout)),
|
||||
// None => value.write(timeval::zero()),
|
||||
// }
|
||||
// size_of::<timeval>()
|
||||
// }
|
||||
// (SOL_SOCKET, SO_BROADCAST) => {
|
||||
// let broadcast =
|
||||
// rt::get_socket_option!(fd, options::Broadcast).e_map_err(Errno::from)?;
|
||||
// let value = value.cast::<c_int>();
|
||||
// value.write(broadcast as c_int);
|
||||
// size_of::<c_int>()
|
||||
// }
|
||||
// (IPPROTO_TCP, TCP_NODELAY) => {
|
||||
// let broadcast = rt::get_socket_option!(fd, options::NoDelay).e_map_err(Errno::from)?;
|
||||
// let value = value.cast::<c_int>();
|
||||
// value.write(broadcast as c_int);
|
||||
// size_of::<c_int>()
|
||||
// }
|
||||
// _ => {
|
||||
// yggdrasil_rt::debug_trace!("Unhandled getsockopt({level}, {name}, {space})");
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
// };
|
||||
|
||||
CIntZeroResult::SUCCESS
|
||||
// CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn setsockopt(
|
||||
fd: c_int,
|
||||
level: c_int,
|
||||
name: c_int,
|
||||
value: *const c_void,
|
||||
size: socklen_t,
|
||||
_fd: c_int,
|
||||
_level: c_int,
|
||||
_name: c_int,
|
||||
_value: *const c_void,
|
||||
_size: socklen_t,
|
||||
) -> CIntZeroResult {
|
||||
if value.is_null() {
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
todo!()
|
||||
// if value.is_null() {
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
// let fd = RawFd::e_try_from(fd)?;
|
||||
|
||||
match (level, name) {
|
||||
(SOL_SOCKET, SO_RCVTIMEO) if size == size_of::<timeval>() => {
|
||||
let timeval = *value.cast::<timeval>();
|
||||
let timeout = timeval.to_duration_opt();
|
||||
rt::set_socket_option::<options::RecvTimeout>(fd, &timeout).e_map_err(Errno::from)?;
|
||||
}
|
||||
(SOL_SOCKET, SO_SNDTIMEO) if size == size_of::<timeval>() => {
|
||||
let timeval = *value.cast::<timeval>();
|
||||
let timeout = timeval.to_duration_opt();
|
||||
rt::set_socket_option::<options::SendTimeout>(fd, &timeout).e_map_err(Errno::from)?;
|
||||
}
|
||||
(SOL_SOCKET, SO_BROADCAST) if size == size_of::<c_int>() => {
|
||||
let value = *value.cast::<c_int>() != 0;
|
||||
rt::set_socket_option::<options::Broadcast>(fd, &value).e_map_err(Errno::from)?;
|
||||
}
|
||||
(IPPROTO_TCP, TCP_NODELAY) if size == size_of::<c_int>() => {
|
||||
let value = *value.cast::<c_int>() != 0;
|
||||
rt::set_socket_option::<options::NoDelay>(fd, &value).e_map_err(Errno::from)?;
|
||||
}
|
||||
_ => {
|
||||
yggdrasil_rt::debug_trace!("Unhandled setsockopt({level}, {name}, {size})");
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
}
|
||||
// match (level, name) {
|
||||
// (SOL_SOCKET, SO_RCVTIMEO) if size == size_of::<timeval>() => {
|
||||
// let timeval = *value.cast::<timeval>();
|
||||
// let timeout = timeval.to_duration_opt();
|
||||
// rt::set_socket_option::<options::RecvTimeout>(fd, &timeout).e_map_err(Errno::from)?;
|
||||
// }
|
||||
// (SOL_SOCKET, SO_SNDTIMEO) if size == size_of::<timeval>() => {
|
||||
// let timeval = *value.cast::<timeval>();
|
||||
// let timeout = timeval.to_duration_opt();
|
||||
// rt::set_socket_option::<options::SendTimeout>(fd, &timeout).e_map_err(Errno::from)?;
|
||||
// }
|
||||
// (SOL_SOCKET, SO_BROADCAST) if size == size_of::<c_int>() => {
|
||||
// let value = *value.cast::<c_int>() != 0;
|
||||
// rt::set_socket_option::<options::Broadcast>(fd, &value).e_map_err(Errno::from)?;
|
||||
// }
|
||||
// (IPPROTO_TCP, TCP_NODELAY) if size == size_of::<c_int>() => {
|
||||
// let value = *value.cast::<c_int>() != 0;
|
||||
// rt::set_socket_option::<options::NoDelay>(fd, &value).e_map_err(Errno::from)?;
|
||||
// }
|
||||
// _ => {
|
||||
// yggdrasil_rt::debug_trace!("Unhandled setsockopt({level}, {name}, {size})");
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
// }
|
||||
|
||||
CIntZeroResult::SUCCESS
|
||||
// CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpeername(
|
||||
fd: c_int,
|
||||
remote: *mut sockaddr,
|
||||
len: *mut socklen_t,
|
||||
_fd: c_int,
|
||||
_remote: *mut sockaddr,
|
||||
_len: *mut socklen_t,
|
||||
) -> CIntZeroResult {
|
||||
if remote.is_null() || len.is_null() {
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
todo!()
|
||||
// if remote.is_null() || len.is_null() {
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let address = rt::get_socket_option!(fd, options::PeerAddress).e_map_err(Errno::from)?;
|
||||
let address = address.e_ok_or(Errno::ENOTCONN)?;
|
||||
// let fd = RawFd::e_try_from(fd)?;
|
||||
// let address = rt::get_socket_option!(fd, options::PeerAddress).e_map_err(Errno::from)?;
|
||||
// let address = address.e_ok_or(Errno::ENOTCONN)?;
|
||||
|
||||
*len = address.to_c(remote, *len)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
// *len = address.to_c(remote, *len)?;
|
||||
// CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getsockname(
|
||||
fd: c_int,
|
||||
local: *mut sockaddr,
|
||||
len: *mut socklen_t,
|
||||
_fd: c_int,
|
||||
_local: *mut sockaddr,
|
||||
_len: *mut socklen_t,
|
||||
) -> CIntZeroResult {
|
||||
if local.is_null() || len.is_null() {
|
||||
error::errno = Errno::EINVAL;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
todo!()
|
||||
// if local.is_null() || len.is_null() {
|
||||
// error::errno = Errno::EINVAL;
|
||||
// return CIntZeroResult::ERROR;
|
||||
// }
|
||||
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let address = rt::get_socket_option!(fd, options::LocalAddress).e_map_err(Errno::from)?;
|
||||
let address = address.e_ok_or(Errno::ENOTCONN)?;
|
||||
// let fd = RawFd::e_try_from(fd)?;
|
||||
// let address = rt::get_socket_option!(fd, options::LocalAddress).e_map_err(Errno::from)?;
|
||||
// let address = address.e_ok_or(Errno::ENOTCONN)?;
|
||||
|
||||
*len = address.to_c(local, *len)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
// *len = address.to_c(local, *len)?;
|
||||
// CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
@ -1,44 +1,59 @@
|
||||
use core::{ffi::c_int, mem::MaybeUninit};
|
||||
use core::{ffi::c_int, net::SocketAddr};
|
||||
|
||||
use yggdrasil_abi::abi_serde::wire;
|
||||
use yggdrasil_rt::{io::RawFd, net as rt, sys as syscall};
|
||||
|
||||
use crate::{
|
||||
error::{self, CFdResult, CIntCountResult, CIntZeroResult, CResult, ResultExt, TryFromExt},
|
||||
headers::{
|
||||
errno::Errno,
|
||||
sys_socket::{AF_INET, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_STREAM},
|
||||
sys_socket::{
|
||||
SocketAddrExt, AF_INET, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_STREAM,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{sockaddr, socklen_t, SocketAddrExt};
|
||||
use super::{sockaddr, socklen_t};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn accept(fd: c_int, remote: *mut sockaddr, len: *mut socklen_t) -> CFdResult {
|
||||
let listener_fd = RawFd::e_try_from(fd)?;
|
||||
let mut address = MaybeUninit::uninit();
|
||||
let stream_fd = syscall::accept(listener_fd, &mut address).e_map_err(Errno::from)?;
|
||||
|
||||
if !remote.is_null() && !len.is_null() {
|
||||
let address = address.assume_init();
|
||||
*len = address.to_c(remote, *len)?;
|
||||
}
|
||||
|
||||
let stream_fd = if remote.is_null() || len.is_null() {
|
||||
syscall::accept(listener_fd, None).e_map_err(Errno::from)?
|
||||
} else {
|
||||
let mut sockaddr_buf = [0; 32];
|
||||
let stream_fd =
|
||||
syscall::accept(listener_fd, Some(&mut sockaddr_buf)).e_map_err(Errno::from)?;
|
||||
let sockaddr: SocketAddr = wire::from_slice(&sockaddr_buf)
|
||||
.map_err(yggdrasil_rt::Error::from)
|
||||
.e_map_err(Errno::from)?;
|
||||
*len = sockaddr.to_c(remote, *len)?;
|
||||
stream_fd
|
||||
};
|
||||
CFdResult::success(stream_fd)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn bind(fd: c_int, local: *const sockaddr, len: socklen_t) -> CIntZeroResult {
|
||||
let mut sockaddr_buf = [0; 32];
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let local = local.to_rust(len)?;
|
||||
syscall::bind(fd, &local).e_map_err(Errno::from)?;
|
||||
let sockaddr_len = wire::to_slice(&local, &mut sockaddr_buf)
|
||||
.map_err(yggdrasil_rt::Error::from)
|
||||
.e_map_err(Errno::from)?;
|
||||
syscall::bind(fd, &sockaddr_buf[..sockaddr_len]).e_map_err(Errno::from)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn connect(fd: c_int, remote: *const sockaddr, len: socklen_t) -> CIntZeroResult {
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let mut sockaddr_buf = [0; 256];
|
||||
let remote = remote.to_rust(len)?;
|
||||
syscall::connect(fd, &remote).e_map_err(Errno::from)?;
|
||||
let sockaddr_len = wire::to_slice(&remote, &mut sockaddr_buf)
|
||||
.map_err(yggdrasil_rt::Error::from)
|
||||
.e_map_err(Errno::from)?;
|
||||
syscall::connect(fd, &sockaddr_buf[..sockaddr_len]).e_map_err(Errno::from)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user