Files
k-os/crates/servers/session-server/src/server.rs
Gabriel Kaszewski 7c7e3b8748 refactor: apply newtypes throughout userspace API and display types
Every syscall stub now uses proper types from types/ — CapSlot,
EntryPoint, StackPointer, VirtualAddress, PageCount, ProcessId,
PermissionSet, Ticks. The compiler prevents swapping entry/stack,
passing a ProcessId where a CapSlot is expected, or using an
address as a page count.

New display types in types/display.rs:
  - Color(u32) with rgb() constructor
  - ScreenCoord(u16) for x/y positions
  - Dimension(u16) for width/height

Updated throughout:
  - userspace/syscall.rs: all params typed, returns Option instead
    of sentinel usize::MAX
  - server-framework: endpoint param is CapSlot
  - port-framebuffer: trait uses Color, ScreenCoord, Dimension
  - hw-virtio: DmaAddrs uses PhysicalAddress/VirtualAddress,
    GPU commands use Dimension
  - All servers, drivers, bins, apps updated for new signatures
  - permission-manager: process field uses ProcessId
  - PermissionSet: added bits() accessor

89 tests pass, full QEMU boot verified.
2026-10-18 13:45:40 +02:00

117 lines
3.1 KiB
Rust

use server_framework::Server;
use types::bounded::CapSlot;
use types::id::ProcessId;
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: ProcessId,
}
pub struct SessionServer {
apps: [Option<AppEntry>; MAX_APPS],
app_count: usize,
running: [Option<RunningApp>; MAX_APPS],
active: Option<AppId>,
create_cap: CapSlot,
}
impl SessionServer {
pub fn new(create_cap: CapSlot) -> Self {
Self {
apps: [const { None }; MAX_APPS],
app_count: 0,
running: [const { None }; MAX_APPS],
active: None,
create_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 process_cap = match userspace::syscall::create_process(self.create_cap) {
Some(cap) => cap,
None => return SessionResponse::Error,
};
let pid = ProcessId::from_raw(process_cap.value() as u16);
self.running[idx] = Some(RunningApp { app, pid });
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) => {
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,
},
}
}
}