refactor: Reimplement recvmsg and sendmsg using bulk fd passing.
This commit is contained in:
committed by
Jeremy Soller
parent
3724e7892d
commit
94b0cfc682
@@ -1,6 +1,7 @@
|
||||
use core::{
|
||||
mem::{replace, size_of},
|
||||
ptr::addr_of,
|
||||
slice,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
@@ -137,6 +138,33 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result<u32> {
|
||||
}
|
||||
.map(|awoken| awoken as u32)
|
||||
}
|
||||
pub fn sys_call_ro(
|
||||
fd: usize,
|
||||
payload: &mut [u8],
|
||||
flags: CallFlags,
|
||||
metadata: &[u64],
|
||||
) -> Result<usize> {
|
||||
sys_call(fd, payload, flags | CallFlags::READ, metadata)
|
||||
}
|
||||
pub fn sys_call_wo(fd: usize, payload: &[u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
|
||||
let payload_mut =
|
||||
unsafe { slice::from_raw_parts_mut(payload.as_ptr() as *mut u8, payload.len()) };
|
||||
|
||||
sys_call(fd, payload_mut, flags | CallFlags::WRITE, metadata)
|
||||
}
|
||||
pub fn sys_call_rw(
|
||||
fd: usize,
|
||||
payload: &mut [u8],
|
||||
flags: CallFlags,
|
||||
metadata: &[u64],
|
||||
) -> Result<usize> {
|
||||
sys_call(
|
||||
fd,
|
||||
payload,
|
||||
flags | CallFlags::READ | CallFlags::WRITE,
|
||||
metadata,
|
||||
)
|
||||
}
|
||||
pub fn sys_call(
|
||||
fd: usize,
|
||||
payload: &mut [u8],
|
||||
|
||||
@@ -63,7 +63,7 @@ impl Dev {
|
||||
) -> Result<c_int> {
|
||||
let mut data = unsafe { buf.read::<T>() }?;
|
||||
let mut wire = unsafe { data.write() };
|
||||
let res = redox_rt::sys::sys_call(
|
||||
let res = redox_rt::sys::sys_call_rw(
|
||||
self.fd as usize,
|
||||
&mut wire,
|
||||
syscall::CallFlags::empty(),
|
||||
@@ -75,11 +75,11 @@ impl Dev {
|
||||
}
|
||||
|
||||
unsafe fn write_ioctl<T: IoctlData>(&self, mut buf: IoctlBuffer, func: u64) -> Result<c_int> {
|
||||
let mut data = unsafe { buf.read::<T>() }?;
|
||||
let mut wire = unsafe { data.write() };
|
||||
let res = redox_rt::sys::sys_call(
|
||||
let data = unsafe { buf.read::<T>() }?;
|
||||
let wire = unsafe { data.write() };
|
||||
let res = redox_rt::sys::sys_call_wo(
|
||||
self.fd as usize,
|
||||
&mut wire,
|
||||
&wire,
|
||||
syscall::CallFlags::empty(),
|
||||
&[func],
|
||||
)?;
|
||||
|
||||
@@ -10,7 +10,7 @@ use redox_rt::{
|
||||
protocol::{ProcKillTarget, SocketCall, WaitFlags},
|
||||
sys::{WaitpidTarget, posix_read, posix_write},
|
||||
};
|
||||
use syscall::{EMFILE, ENOSYS, Error, Result};
|
||||
use syscall::{CallFlags, EMFILE, ENOSYS, Error, Result};
|
||||
|
||||
use crate::{
|
||||
header::{
|
||||
@@ -455,7 +455,7 @@ pub unsafe extern "C" fn redox_get_socket_token_v0(
|
||||
payload_len: usize,
|
||||
) -> RawResult {
|
||||
let metadata = [SocketCall::GetToken as u64];
|
||||
Error::mux(redox_rt::sys::sys_call(
|
||||
Error::mux(redox_rt::sys::sys_call_ro(
|
||||
fd,
|
||||
unsafe { slice::from_raw_parts_mut(payload, payload_len) },
|
||||
syscall::CallFlags::empty(),
|
||||
|
||||
@@ -266,14 +266,17 @@ unsafe fn serialize_ancillary_data_to_stream(
|
||||
}
|
||||
let fd_count = data_len / mem::size_of::<c_int>();
|
||||
|
||||
// Call syscall::sendfd for each fd.
|
||||
if fd_count > 0 {
|
||||
let fds_ptr = unsafe { CMSG_DATA(cmsg) } as *const c_int;
|
||||
let fds_slice = unsafe { slice::from_raw_parts(fds_ptr, fd_count) };
|
||||
for &fd in fds_slice.iter() {
|
||||
let fd_to_send = FdGuard::new(syscall::dup(fd as usize, b"")?);
|
||||
syscall::sendfd(socket as usize, fd_to_send.as_raw_fd(), 0, 0)?;
|
||||
}
|
||||
let c_fds = unsafe { slice::from_raw_parts(fds_ptr, fd_count) };
|
||||
let fds_usize: Vec<usize> = c_fds.iter().map(|&fd| fd as usize).collect();
|
||||
let fds_slice = unsafe {
|
||||
slice::from_raw_parts(
|
||||
fds_usize.as_ptr() as *const u8,
|
||||
fds_usize.len() * mem::size_of::<usize>(),
|
||||
)
|
||||
};
|
||||
redox_rt::sys::sys_call_wo(socket as usize, &fds_slice, CallFlags::FD, &[])?;
|
||||
}
|
||||
|
||||
// Serialize to ancillary_data_stream.
|
||||
@@ -437,10 +440,19 @@ unsafe fn deserialize_ancillary_data_from_stream(
|
||||
}
|
||||
let fd_count = read_num::<usize>(&cmsg_data_from_stream)?;
|
||||
|
||||
for _ in 0..fd_count {
|
||||
// Call syscall::dup to duplicate the fd
|
||||
let new_fd = syscall::dup(socket as usize, b"recvfd")?;
|
||||
temp_posix_cmsg_data_buf.extend_from_slice(&(new_fd as c_int).to_le_bytes());
|
||||
let mut fds_usize = vec![0usize; fd_count];
|
||||
|
||||
let fds_bytes = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
fds_usize.as_mut_ptr() as *mut u8,
|
||||
fds_usize.len() * mem::size_of::<usize>(),
|
||||
)
|
||||
};
|
||||
|
||||
redox_rt::sys::sys_call_ro(socket as usize, fds_bytes, CallFlags::FD, &[])?;
|
||||
|
||||
for fd in fds_usize {
|
||||
temp_posix_cmsg_data_buf.extend_from_slice(&(fd as c_int).to_le_bytes());
|
||||
}
|
||||
actual_posix_cmsg_data_len = temp_posix_cmsg_data_buf.len();
|
||||
}
|
||||
@@ -552,9 +564,9 @@ impl PalSocket for Sys {
|
||||
|
||||
let (dir_path, mut fd_path) = dir_path_and_fd_path(&path)?;
|
||||
|
||||
redox_rt::sys::sys_call(
|
||||
redox_rt::sys::sys_call_wo(
|
||||
socket as usize,
|
||||
unsafe { fd_path.as_bytes_mut() },
|
||||
fd_path.as_bytes(),
|
||||
CallFlags::empty(),
|
||||
&[SocketCall::Bind as u64],
|
||||
)?;
|
||||
@@ -570,9 +582,9 @@ impl PalSocket for Sys {
|
||||
})();
|
||||
|
||||
if let Err(original_error) = fs_bind_result {
|
||||
if let Err(unbind_error) = redox_rt::sys::sys_call(
|
||||
if let Err(unbind_error) = redox_rt::sys::sys_call_wo(
|
||||
socket as usize,
|
||||
&mut [],
|
||||
&[],
|
||||
CallFlags::empty(),
|
||||
&[SocketCall::Unbind as u64],
|
||||
) {
|
||||
@@ -636,16 +648,16 @@ impl PalSocket for Sys {
|
||||
|
||||
let mut token_buf = [0u8; TOKEN_BUF_SIZE];
|
||||
|
||||
redox_rt::sys::sys_call(
|
||||
redox_rt::sys::sys_call_ro(
|
||||
socket_file_fd.as_raw_fd(),
|
||||
&mut token_buf,
|
||||
CallFlags::empty(),
|
||||
&[FsCall::Connect as u64],
|
||||
)?;
|
||||
|
||||
redox_rt::sys::sys_call(
|
||||
redox_rt::sys::sys_call_wo(
|
||||
socket as usize,
|
||||
&mut token_buf,
|
||||
&token_buf,
|
||||
CallFlags::empty(),
|
||||
&[SocketCall::Connect as u64],
|
||||
)?;
|
||||
@@ -661,7 +673,7 @@ impl PalSocket for Sys {
|
||||
address_len: *mut socklen_t,
|
||||
) -> Result<()> {
|
||||
let mut buf = [0; 256];
|
||||
let len = redox_rt::sys::sys_call(
|
||||
let len = redox_rt::sys::sys_call_ro(
|
||||
socket as usize,
|
||||
&mut buf,
|
||||
CallFlags::empty(),
|
||||
@@ -733,7 +745,7 @@ impl PalSocket for Sys {
|
||||
unsafe { slice::from_raw_parts_mut(option_value as *mut u8, option_len) };
|
||||
let call_flags = CallFlags::empty();
|
||||
unsafe {
|
||||
*option_len_ptr = redox_rt::sys::sys_call(
|
||||
*option_len_ptr = redox_rt::sys::sys_call_ro(
|
||||
socket as usize,
|
||||
payload,
|
||||
CallFlags::empty(),
|
||||
@@ -863,7 +875,7 @@ impl PalSocket for Sys {
|
||||
let metadata = [SocketCall::RecvMsg as u64, flags as u64];
|
||||
let call_flags = CallFlags::empty();
|
||||
let actual_read_len =
|
||||
redox_rt::sys::sys_call(socket as usize, &mut msg_stream, call_flags, &metadata)?;
|
||||
redox_rt::sys::sys_call_rw(socket as usize, &mut msg_stream, call_flags, &metadata)?;
|
||||
msg_stream.truncate(actual_read_len);
|
||||
|
||||
cursor = 0;
|
||||
@@ -944,7 +956,7 @@ impl PalSocket for Sys {
|
||||
// Send the message stream.
|
||||
let metadata = [SocketCall::SendMsg as u64, flags as u64];
|
||||
let call_flags = CallFlags::empty();
|
||||
let written = redox_rt::sys::sys_call(
|
||||
let written = redox_rt::sys::sys_call_rw(
|
||||
socket as usize,
|
||||
msg_stream.as_mut_slice(),
|
||||
call_flags,
|
||||
@@ -1036,7 +1048,7 @@ impl PalSocket for Sys {
|
||||
slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize)
|
||||
};
|
||||
let call_flags = CallFlags::empty();
|
||||
redox_rt::sys::sys_call(
|
||||
redox_rt::sys::sys_call_rw(
|
||||
socket as usize,
|
||||
payload,
|
||||
CallFlags::empty(),
|
||||
@@ -1062,7 +1074,7 @@ impl PalSocket for Sys {
|
||||
|
||||
fn shutdown(socket: c_int, how: c_int) -> Result<()> {
|
||||
let metadata = [SocketCall::Shutdown as u64, how as u64];
|
||||
redox_rt::sys::sys_call(socket as usize, &mut [], CallFlags::empty(), &metadata)?;
|
||||
redox_rt::sys::sys_call_wo(socket as usize, &[], CallFlags::empty(), &metadata)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user