From 771fffbfd6087a7a94121cf8da3f061539b48c45 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 20 Dec 2023 19:12:51 +0100 Subject: [PATCH] Migrate to libredox and redox-scheme. --- Cargo.lock | 74 ++++++++++++++++++++++-- Cargo.toml | 7 ++- src/chan.rs | 29 ++++------ src/main.rs | 159 ++++++++++++++++++++++------------------------------ src/shm.rs | 19 ++----- 5 files changed, 156 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95af9bb638..d7b714e559 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,24 +8,86 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "ipcd" version = "0.1.0" dependencies = [ - "libc", + "libredox 0.0.3", + "redox-daemon", + "redox-scheme", + "redox_event", "redox_syscall", ] [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + +[[package]] +name = "libredox" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962b650e6b934f95cec493e1464e0f5cba98dd9ba9ef2b1c42cdfdb7864cab5a" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + +[[package]] +name = "redox-daemon" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353178b5771a301b9d2b318914ab5dfeb21dd6e65930faedde19248cfceca5a7" +dependencies = [ + "libc", + "libredox 0.0.1", +] + +[[package]] +name = "redox-scheme" +version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#265e056726066f319e47eedd5f20f9549fb4c581" +dependencies = [ + "libredox 0.0.3", + "redox_syscall", +] + +[[package]] +name = "redox_event" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b78fedc17aea72caee38ac1208e0f709fa1641af1bbe0205e7d434413a60621d" +dependencies = [ + "bitflags 2.4.1", + "libredox 0.0.1", + "redox_syscall", +] [[package]] name = "redox_syscall" -version = "0.3.5" -source = "git+https://gitlab.redox-os.org/4lDO2/syscall.git?branch=better_fmap#f0976e1d6020e6854ca30ed1f6d61b10dfc4fa58" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] diff --git a/Cargo.toml b/Cargo.toml index 51ce678bc1..1cec1ae4ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,8 @@ name = "ipcd" version = "0.1.0" [dependencies] -libc = "0.2" -redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } +libredox = "0.0.3" +redox-daemon = "0.1.2" +redox_syscall = "0.4.1" +redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } +redox_event = "0.2.0" diff --git a/src/chan.rs b/src/chan.rs index 717e59257f..13a79dcc91 100644 --- a/src/chan.rs +++ b/src/chan.rs @@ -1,12 +1,9 @@ -use crate::post_fevent; use std::{ cmp, collections::{HashMap, VecDeque}, - fs::{File, OpenOptions}, - io, - os::unix::fs::OpenOptionsExt, }; -use syscall::{flag::*, error::*, Error, SchemeBlockMut, Result}; +use syscall::{flag::*, error::*, Error}; +use redox_scheme::SchemeBlockMut; #[derive(Debug, Default)] pub struct Client { @@ -42,7 +39,6 @@ impl Default for Connection { #[derive(Debug, Default)] pub struct Handle { - id: usize, flags: usize, extra: Extra, path: Option, @@ -96,20 +92,15 @@ pub struct ChanScheme { handles: HashMap, listeners: HashMap, next_id: usize, - pub socket: File + pub socket: redox_scheme::Socket, } impl ChanScheme { - pub fn new() -> io::Result { + pub fn new() -> Result { Ok(Self { handles: HashMap::new(), listeners: HashMap::new(), next_id: 0, - socket: OpenOptions::new() - .read(true) - .write(true) - .create(true) - .custom_flags(O_NONBLOCK as i32) - .open(":chan")? + socket: redox_scheme::Socket::nonblock("chan")?, }) } } @@ -147,7 +138,7 @@ impl SchemeBlockMut for ChanScheme { // smoltcp sends writeable whenever a listener gets a // client, we'll do the same too (but also readable, why // not) - post_fevent(&mut self.socket, listener_id, EVENT_READ | EVENT_WRITE)?; + self.socket.post_fevent(listener_id, (EVENT_READ | EVENT_WRITE).bits())?; } self.handles.insert(new_id, new); @@ -179,7 +170,7 @@ impl SchemeBlockMut for ChanScheme { }, Extra::Listener(_) => panic!("newly created handle can't possibly be a listener") } - post_fevent(&mut self.socket, remote_id, EVENT_WRITE)?; + self.socket.post_fevent(remote_id, EVENT_WRITE.bits())?; new.path = listener_path; @@ -204,7 +195,7 @@ impl SchemeBlockMut for ChanScheme { // smoltcp sends writeable whenever a listener gets a // client, we'll do the same too (but also readable, // why not) - post_fevent(&mut self.socket, id, EVENT_READ | EVENT_WRITE)?; + self.socket.post_fevent(id, (EVENT_READ | EVENT_WRITE).bits())?; self.handles.insert(new_id, new); self.next_id += 1; @@ -249,7 +240,7 @@ impl SchemeBlockMut for ChanScheme { if client.buffer.len() == buf.len() { // Send readable only if it wasn't readable // before - post_fevent(&mut self.socket, remote_id, EVENT_READ)?; + self.socket.post_fevent(remote_id, EVENT_READ.bits())?; } Ok(Some(buf.len())) }, @@ -316,7 +307,7 @@ impl SchemeBlockMut for ChanScheme { if client.buffer.is_empty() { // Post readable on EOF only if it wasn't // readable before - post_fevent(&mut self.socket, remote_id, EVENT_READ)?; + self.socket.post_fevent(remote_id, EVENT_READ.bits())?; } }, Extra::Listener(_) => panic!("a client can't be connected to a listener!") diff --git a/src/main.rs b/src/main.rs index bde573ea2a..d91c06f750 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,9 @@ -#![feature(int_roundings)] +#![feature(int_roundings, let_chains)] -use std::{ - collections::VecDeque, - fs::File, - io::{self, prelude::*}, - os::unix::io::AsRawFd -}; -use syscall::{flag::*, error, Error, Event, Packet, SchemeBlockMut, SchemeMut}; +use std::collections::VecDeque; +use event::{EventQueue, EventFlags}; +use redox_scheme::{SignalBehavior, Response}; +use syscall::{Error, Result, EAGAIN, EWOULDBLOCK, ENODEV}; mod chan; mod shm; @@ -14,77 +11,76 @@ mod shm; use self::chan::ChanScheme; use self::shm::ShmScheme; -fn from_syscall_error(error: syscall::Error) -> io::Error { - io::Error::from_raw_os_error(error.errno as i32) +fn main() { + redox_daemon::Daemon::new(move |daemon| { + // TODO: Better error handling + match inner(daemon) { + Ok(()) => std::process::exit(0), + Err(error) => { + println!("ipcd failed: {error}"); + std::process::exit(1); + } + } + }).expect("ipcd: failed to daemonize"); } -const TOKEN_CHAN: usize = 0; -const TOKEN_SHM: usize = 1; - -fn main() -> Result<(), Box> { - match unsafe { libc::fork() } { - 0 => (), - -1 => return Err(Box::new(io::Error::last_os_error())), - _child => return Ok(()), +fn inner(daemon: redox_daemon::Daemon) -> Result<()> { + event::user_data! { + enum EventSource { + ChanSocket, + ShmSocket, + } } + let chan = ChanScheme::new()?; + let shm = ShmScheme::new()?; + daemon.ready().unwrap(); // Create event listener for both files - let mut event_file = File::open("event:")?; + let mut event_queue = EventQueue::::new()?; - let chan = ChanScheme::new()?; - event_file.write(&Event { - id: chan.socket.as_raw_fd() as usize, - flags: EVENT_READ, - data: TOKEN_CHAN - })?; - let shm = ShmScheme::new()?; - event_file.write(&Event { - id: shm.socket.as_raw_fd() as usize, - flags: EVENT_READ, - data: TOKEN_SHM - })?; + event_queue.subscribe(chan.socket.inner().raw(), EventSource::ChanSocket, EventFlags::READ)?; + event_queue.subscribe(shm.socket.inner().raw(), EventSource::ShmSocket, EventFlags::READ)?; let mut todo = VecDeque::with_capacity(16); - syscall::setrens(0, 0).map_err(from_syscall_error)?; + libredox::call::setrens(0, 0)?; let mut chan_opt = Some(chan); let mut shm_opt = Some(shm); while chan_opt.is_some() || shm_opt.is_some() { - let mut event = Event::default(); - event_file.read(&mut event)?; + let Some(event_res) = event_queue.next() else { + break; + }; + let event = event_res?; - match event.data { - TOKEN_CHAN => { - let mut error: Option = None; + match event.user_data { + EventSource::ChanSocket => { + let mut error: Option = None; let unmount = if let Some(ref mut chan) = chan_opt { let eof = loop { - let mut packet = Packet::default(); - match chan.socket.read(&mut packet) { - Ok(0) => break true, - Ok(_) => todo.push_front(packet), - Err(err) => if err.kind() == io::ErrorKind::WouldBlock { - break false; - } else { - return Err(Box::new(err)); - } - }; + match chan.socket.next_request(SignalBehavior::Restart) { + Ok(None) => break true, + Ok(Some(request)) => todo.push_front(Some(request)), + Err(Error { errno: EAGAIN | EWOULDBLOCK }) => break false, + Err(error) => return Err(error), + } }; // Process queue, delete finished items - todo.retain(|packet| { - if let Some(status) = chan.handle(&packet) { - // Send packet back with new ID - let mut packet = *packet; - packet.a = status; - if let Err(err) = chan.socket.write(&packet) { - error = Some(err); + todo.retain_mut(|request_opt| { + match request_opt.take().unwrap().handle_scheme_block_mut(chan) { + Ok(res) => { + if let Err(err) = chan.socket.write_response(res, SignalBehavior::Restart) { + error = Some(err); + } + return false; + } + Err(req) => { + *request_opt = Some(req); + true } - return false; } - - true }); eof @@ -92,38 +88,29 @@ fn main() -> Result<(), Box> { false }; - if unmount { - if let Some(mut chan) = chan_opt.take() { - for mut packet in todo.drain(..) { - packet.a = Error::mux(Err(Error::new(error::ENODEV))); - if let Err(err) = chan.socket.write(&packet) { - error = Some(err); - } + if unmount && let Some(chan) = chan_opt.take() { + for req in todo.drain(..) { + if let Err(err) = chan.socket.write_response(Response::new(&req.unwrap(), Err(Error::new(ENODEV))), SignalBehavior::Restart) { + error = Some(err); } } } if let Some(err) = error { - return Err(Box::new(err)); + return Err(err); } }, - TOKEN_SHM => { + EventSource::ShmSocket => { let unmount = if let Some(ref mut shm) = shm_opt { let eof = loop { - let mut packet = Packet::default(); - match shm.socket.read(&mut packet) { - Ok(0) => break true, - Ok(_) => { - unsafe { - shm.handle(&mut packet); - } - shm.socket.write(&packet)?; + match shm.socket.next_request(SignalBehavior::Restart) { + Ok(None) => break true, + Ok(Some(request)) => { + let response = request.handle_scheme_mut(shm); + shm.socket.write_response(response, SignalBehavior::Restart)?; }, - Err(err) => if err.kind() == io::ErrorKind::WouldBlock { - break false; - } else { - return Err(Box::new(err)); - } + Err(Error { errno: EAGAIN | EWOULDBLOCK }) => break false, + Err(err) => return Err(err), }; }; @@ -135,21 +122,9 @@ fn main() -> Result<(), Box> { if unmount { shm_opt.take(); } - }, - _ => () + } } } Ok(()) } -fn post_fevent(file: &mut File, id: usize, flag: EventFlags) -> syscall::Result<()> { - file.write(&syscall::Packet { - a: syscall::SYS_FEVENT, - b: id, - c: flag.bits(), - d: 1, - ..Default::default() - }) - .map(|_| ()) - .map_err(|_| Error::new(error::EIO)) -} diff --git a/src/shm.rs b/src/shm.rs index db7c8a1ce7..732e519f7e 100644 --- a/src/shm.rs +++ b/src/shm.rs @@ -1,12 +1,10 @@ use std::{ cmp, collections::{HashMap, hash_map::Entry}, - fs::{File, OpenOptions}, - io, - os::unix::fs::OpenOptionsExt, rc::Rc, }; -use syscall::{error::*, flag::O_NONBLOCK, Error, Map, SchemeMut, Result, Packet, KSMSG_MMAP_PREP, MapFlags, KSMSG_MMAP, PAGE_SIZE, MAP_PRIVATE}; +use syscall::{error::*, Error, Map, Result, MapFlags, PAGE_SIZE, MAP_PRIVATE}; +use redox_scheme::SchemeMut; #[derive(Default)] pub struct ShmHandle { @@ -17,20 +15,15 @@ pub struct ShmScheme { maps: HashMap, ShmHandle>, handles: HashMap>, next_id: usize, - pub socket: File + pub socket: redox_scheme::Socket, } impl ShmScheme { - pub fn new() -> io::Result { + pub fn new() -> Result { Ok(Self { maps: HashMap::new(), handles: HashMap::new(), next_id: 0, - socket: OpenOptions::new() - .read(true) - .write(true) - .create(true) - .custom_flags(O_NONBLOCK as i32) - .open(":shm")? + socket: redox_scheme::Socket::nonblock("shm")?, }) } } @@ -75,7 +68,7 @@ impl SchemeMut for ShmScheme { } Ok(0) } - fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result { + fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, _: MapFlags) -> Result { let path = self.handles.get(&id).ok_or(Error::new(EBADF))?; let total_size = offset as usize + size; match self.maps.get_mut(path).expect("handle pointing to nothing").buffer {