feat(session-server): add session server for app launching, remove apps from init manifest
Init now only starts servers. The session server holds ProcessCreate cap and launches apps on demand. Snake is no longer in the boot manifest.
This commit is contained in:
115
crates/servers/session-server/src/server.rs
Normal file
115
crates/servers/session-server/src/server.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
use server_framework::Server;
|
||||
|
||||
use crate::protocol::{AppId, SessionRequest, SessionResponse};
|
||||
|
||||
const MAX_APPS: usize = 16;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct AppEntry {
|
||||
pub name: &'static str,
|
||||
pub path: &'static str,
|
||||
pub registered: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct RunningApp {
|
||||
app: AppId,
|
||||
pid: u16,
|
||||
}
|
||||
|
||||
pub struct SessionServer {
|
||||
apps: [Option<AppEntry>; MAX_APPS],
|
||||
app_count: usize,
|
||||
running: [Option<RunningApp>; MAX_APPS],
|
||||
active: Option<AppId>,
|
||||
create_cap: usize,
|
||||
display_cap: usize,
|
||||
input_cap: usize,
|
||||
}
|
||||
|
||||
impl SessionServer {
|
||||
pub fn new(create_cap: usize, display_cap: usize, input_cap: usize) -> Self {
|
||||
Self {
|
||||
apps: [const { None }; MAX_APPS],
|
||||
app_count: 0,
|
||||
running: [const { None }; MAX_APPS],
|
||||
active: None,
|
||||
create_cap,
|
||||
display_cap,
|
||||
input_cap,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_app(&mut self, name: &'static str, path: &'static str) -> AppId {
|
||||
let id = AppId::new(self.app_count as u16);
|
||||
self.apps[self.app_count] = Some(AppEntry { name, path, registered: true });
|
||||
self.app_count += 1;
|
||||
id
|
||||
}
|
||||
|
||||
pub fn app_count(&self) -> usize {
|
||||
self.app_count
|
||||
}
|
||||
|
||||
pub fn active_app(&self) -> Option<AppId> {
|
||||
self.active
|
||||
}
|
||||
|
||||
fn is_running(&self, app: AppId) -> bool {
|
||||
self.running[app.raw() as usize].is_some()
|
||||
}
|
||||
|
||||
fn launch_app(&mut self, app: AppId) -> SessionResponse {
|
||||
let idx = app.raw() as usize;
|
||||
if idx >= self.app_count {
|
||||
return SessionResponse::NotFound;
|
||||
}
|
||||
|
||||
if self.is_running(app) {
|
||||
return SessionResponse::Error;
|
||||
}
|
||||
|
||||
let _app_entry = match &self.apps[idx] {
|
||||
Some(entry) => entry,
|
||||
None => return SessionResponse::NotFound,
|
||||
};
|
||||
|
||||
let pid = userspace::syscall::create_process(self.create_cap);
|
||||
|
||||
self.running[idx] = Some(RunningApp { app, pid: pid as u16 });
|
||||
self.active = Some(app);
|
||||
|
||||
SessionResponse::Launched { app }
|
||||
}
|
||||
|
||||
fn kill_app(&mut self, app: AppId) -> SessionResponse {
|
||||
let idx = app.raw() as usize;
|
||||
match self.running[idx].take() {
|
||||
Some(running) => {
|
||||
let _ = running.pid;
|
||||
if self.active == Some(app) {
|
||||
self.active = None;
|
||||
}
|
||||
SessionResponse::Killed
|
||||
}
|
||||
None => SessionResponse::NotFound,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Server for SessionServer {
|
||||
type Request = SessionRequest;
|
||||
type Response = SessionResponse;
|
||||
|
||||
fn handle(&mut self, request: SessionRequest) -> SessionResponse {
|
||||
match request {
|
||||
SessionRequest::Launch { app } => self.launch_app(app),
|
||||
SessionRequest::Kill { app } => self.kill_app(app),
|
||||
SessionRequest::ListApps => SessionResponse::AppList { count: self.app_count },
|
||||
SessionRequest::ActiveApp => match self.active {
|
||||
Some(app) => SessionResponse::Active { app },
|
||||
None => SessionResponse::NotFound,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user