diff --git a/Cargo.lock b/Cargo.lock index 9efe0a7..d983db6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,7 @@ dependencies = [ "flatbuffers", "flexbuffers", "mint", + "mio", "nanoid", "schemas", "thiserror", @@ -347,6 +348,7 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" name = "stardust-xr" version = "0.9.0" dependencies = [ + "anyhow", "libstardustxr", "mio", "slab", diff --git a/Cargo.toml b/Cargo.toml index d89990b..dccddc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,6 @@ version = "0.9.0" [dependencies] libstardustxr = {path = "../libstardustxr-rs"} -mio = {version = "0.8.3", features = ["net", "os-poll"]} +anyhow = "1.0.57" +mio = {version = "0.8.3", features = ["net", "os-poll", "os-ext"]} slab = "0.4.6" \ No newline at end of file diff --git a/src/core/client.rs b/src/core/client.rs new file mode 100644 index 0000000..c7bfb33 --- /dev/null +++ b/src/core/client.rs @@ -0,0 +1,25 @@ +use libstardustxr::fusion::scenegraph::Scenegraph; +use libstardustxr::messenger::Messenger; +use mio::net::UnixStream; +use std::rc::{Rc, Weak}; + +pub struct Client<'a> { + pub messenger: Rc>, + pub scenegraph: Scenegraph<'a>, +} + +impl<'a> Client<'a> { + pub fn from_connection(connection: UnixStream) -> Self { + Client { + scenegraph: Scenegraph::new(), + messenger: Rc::new(Messenger::new(connection)), + } + } + pub fn dispatch(&self) -> Result<(), std::io::Error> { + self.messenger.dispatch(&self.scenegraph) + } + + pub fn get_weak_messenger(&self) -> Weak> { + Rc::downgrade(&self.messenger) + } +} diff --git a/src/core/eventloop.rs b/src/core/eventloop.rs index 766b047..74ca3e8 100644 --- a/src/core/eventloop.rs +++ b/src/core/eventloop.rs @@ -1,21 +1,81 @@ -use libstardustxr::fusion::client::Client; +use super::client::Client; use libstardustxr::server; use mio::net::UnixListener; +use mio::unix::pipe; +use mio::{Events, Interest, Poll, Token}; use slab::Slab; +use std::io::Write; +use std::thread::{self, JoinHandle}; -pub struct EventLoop<'a> { +use anyhow::Result; + +pub struct EventLoop { pub socket_path: String, - listener: UnixListener, - clients: Slab>, + join_handle: Option>>, + stop_write: pipe::Sender, } -impl<'a> EventLoop<'a> { - pub fn new() -> Option { - let socket_path = server::get_free_socket_path()?; - Some(EventLoop { - listener: UnixListener::bind(socket_path.clone()).ok()?, +impl EventLoop { + pub fn new(timeout: Option) -> Result { + let socket_path = server::get_free_socket_path() + .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::Other))?; + let mut socket = UnixListener::bind(socket_path.clone())?; + let (sender, mut receiver) = pipe::new()?; + let join_handle = Some(thread::spawn(move || -> Result<()> { + let mut clients: Slab = Slab::new(); + let mut poll = Poll::new()?; + let mut events = Events::with_capacity(1024); + const LISTENER: Token = Token(usize::MAX - 1); + poll.registry() + .register(&mut socket, LISTENER, Interest::READABLE)?; + const STOP: Token = Token(usize::MAX); + poll.registry() + .register(&mut receiver, STOP, Interest::READABLE)?; + loop { + poll.poll(&mut events, timeout)?; + for event in &events { + match event.token() { + LISTENER => loop { + match socket.accept() { + Ok((socket, _)) => { + clients.insert(Client::from_connection(socket)); + } + Err(e) => { + if e.kind() == std::io::ErrorKind::WouldBlock { + break; + } + return Err(e.into()); + } + } + }, + STOP => return Ok(()), + token => loop { + match clients.get(token.0).unwrap().dispatch() { + Ok(_) => continue, + Err(e) => { + if e.kind() == std::io::ErrorKind::WouldBlock { + break; + } + return Err(e.into()); + } + } + }, + } + } + } + })); + Ok(EventLoop { socket_path, - clients: Slab::new(), + join_handle, + stop_write: sender, }) } } + +impl Drop for EventLoop { + fn drop(&mut self) { + let buf: [u8; 1] = [1; 1]; + let _ = self.stop_write.write(buf.as_slice()); + let _ = self.join_handle.take().unwrap().join(); + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs index 3e3a2ce..cd46d1c 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1 +1,2 @@ +pub mod client; pub mod eventloop; diff --git a/src/main.rs b/src/main.rs index 3175a13..f7ec431 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,6 @@ use self::core::eventloop::EventLoop; fn main() { println!("Setting up Stardust socket..."); - let event_loop = EventLoop::new().expect("Couldn't create server socket"); + let event_loop = EventLoop::new(None).expect("Couldn't create server socket"); println!("Stardust socket created at {}", event_loop.socket_path); }