Migrate to libredox and redox-scheme.

This commit is contained in:
4lDO2
2023-12-20 19:12:51 +01:00
parent c787931b33
commit 771fffbfd6
5 changed files with 156 additions and 132 deletions
Generated
+68 -6
View File
@@ -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",
]
+5 -2
View File
@@ -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"
+10 -19
View File
@@ -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<String>,
@@ -96,20 +92,15 @@ pub struct ChanScheme {
handles: HashMap<usize, Handle>,
listeners: HashMap<String, usize>,
next_id: usize,
pub socket: File
pub socket: redox_scheme::Socket,
}
impl ChanScheme {
pub fn new() -> io::Result<Self> {
pub fn new() -> Result<Self> {
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!")
+67 -92
View File
@@ -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<dyn std::error::Error>> {
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::<EventSource>::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<io::Error> = None;
match event.user_data {
EventSource::ChanSocket => {
let mut error: Option<Error> = 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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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))
}
+6 -13
View File
@@ -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<Rc<str>, ShmHandle>,
handles: HashMap<usize, Rc<str>>,
next_id: usize,
pub socket: File
pub socket: redox_scheme::Socket,
}
impl ShmScheme {
pub fn new() -> io::Result<Self> {
pub fn new() -> Result<Self> {
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<usize> {
fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, _: MapFlags) -> Result<usize> {
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 {