diff --git a/src/lib.rs b/src/lib.rs index dbf5af2ff08685187175151e13073e9765a5415f..e0c7763b7616168833fda812e6f66db2fdcaa400 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,8 @@ use core::str; use libredox::flag; use syscall::schemev2::{Cqe, CqeOpcode, NewFdFlags, Opcode, Sqe}; use syscall::{ - Error, EventFlags, MapFlags, MunmapFlags, Packet, Result, Stat, StatVfs, TimeSpec, EBADF, - EINTR, EINVAL, ENOENT, EOPNOTSUPP, + Error, EventFlags, FobtainFdFlags, MapFlags, MunmapFlags, Packet, Result, SendFdFlags, Stat, + StatVfs, TimeSpec, EBADF, EINTR, EINVAL, ENOENT, EOPNOTSUPP, }; pub use self::scheme_block::SchemeBlock; @@ -78,9 +78,14 @@ pub struct CallRequest { inner: Request, } +pub struct SendFdRequest { + inner: Request, +} + pub enum RequestKind { Call(CallRequest), Cancellation(CancellationRequest), + SendFd(SendFdRequest), MsyncMsg, MunmapMsg, MmapMsg, @@ -397,6 +402,51 @@ impl CallRequest { } } +impl SendFdRequest { + #[inline] + pub fn request(&self) -> Request { + self.inner + } + + pub fn id(&self) -> usize { + self.inner.sqe.args[0] as usize + } + + pub fn flags(&self) -> SendFdFlags { + SendFdFlags::from_bits_retain(self.inner.sqe.args[1] as usize) + } + + pub fn obtain_fd( + &self, + socket: &Socket, + flags: FobtainFdFlags, + dst_fd_or_ptr: Result<usize, &mut usize>, + ) -> Result<()> { + assert!(!flags.contains(FobtainFdFlags::MANUAL_FD)); + match dst_fd_or_ptr { + Ok(dst_fd) => { + socket.inner.write(&Cqe { + flags: CqeOpcode::ObtainFd as u8, + extra_raw: usize::to_ne_bytes((flags | FobtainFdFlags::MANUAL_FD).bits())[..3] + .try_into() + .unwrap(), + tag: self.inner.request_id().0, + result: dst_fd as u64, + })?; + } + Err(ptr) => { + socket.inner.write(&Cqe { + flags: CqeOpcode::ObtainFd as u8, + extra_raw: usize::to_ne_bytes(flags.bits())[..3].try_into().unwrap(), + tag: self.inner.request_id().0, + result: ptr as *mut usize as u64, + })?; + } + } + Ok(()) + } +} + impl Request { #[inline] pub fn context_id(&self) -> usize { @@ -411,6 +461,9 @@ impl Request { Some(Opcode::Cancel) => RequestKind::Cancellation(CancellationRequest { id: Id(self.sqe.tag), }), + Some(Opcode::Sendfd) => RequestKind::SendFd(SendFdRequest { + inner: Request { sqe: self.sqe }, + }), Some(Opcode::Msync) => RequestKind::MsyncMsg, //Some(Opcode::Munmap) => RequestKind::MunmapMsg, Some(Opcode::RequestMmap) => RequestKind::MmapMsg, @@ -491,6 +544,15 @@ impl Response { tag: req.inner.sqe.tag, }) } + + pub fn for_sendfd(req: &SendFdRequest, status: Result<usize>) -> Self { + Self(Cqe { + flags: CqeOpcode::RespondRegular as u8, + extra_raw: [0_u8; 3], + result: Error::mux(status) as u64, + tag: req.inner.sqe.tag, + }) + } } pub enum SignalBehavior {