Files
k-os/crates/servers/storage-server/src/protocol.rs

129 lines
4.6 KiB
Rust

//! Storage protocol: a client `Attach`es to get a shared buffer; paths and
//! data travel through it, message words carry only lengths and handles.
use server_framework::{Decode, Encode};
use crate::filesystem::FileHandle;
pub use types::storage::{BUFFER_PAGES, BUFFER_SIZE, DIR_ENTRY_SIZE, DIR_NAME_SIZE, MAX_PATH};
use types::storage::{op, reply};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StorageRequest {
Attach,
/// The path is the first `path_len` bytes of the buffer.
Open { path_len: usize },
/// Reads up to `len` bytes into the buffer.
Read { handle: FileHandle, len: usize },
/// Writes the first `len` bytes of the buffer.
Write { handle: FileHandle, len: usize },
Close { handle: FileHandle },
FileSize { handle: FileHandle },
/// Fills the buffer with `DIR_ENTRY_SIZE` records.
ListDir { path_len: usize },
Create { path_len: usize },
Delete { path_len: usize },
Mkdir { path_len: usize },
/// Carries the endpoint to print to.
SetLog,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StorageResponse {
/// Carries the buffer capability; `size` bytes are usable.
Attached { size: usize },
Handle(FileHandle),
Data { bytes: usize },
Written { bytes: usize },
Ok,
DirEntries { count: usize },
Size(usize),
NotFound,
Error,
/// The disk cannot be written.
ReadOnly,
/// The client has not attached a buffer yet.
NotAttached,
}
fn handle(word: usize) -> Option<FileHandle> {
u16::try_from(word).ok().map(FileHandle::new)
}
impl Encode for StorageRequest {
fn encode(&self) -> [usize; 4] {
use StorageRequest::*;
match *self {
Attach => [op::ATTACH, 0, 0, 0],
Open { path_len } => [op::OPEN, path_len, 0, 0],
Read { handle, len } => [op::READ, handle.raw() as usize, len, 0],
Write { handle, len } => [op::WRITE, handle.raw() as usize, len, 0],
Close { handle } => [op::CLOSE, handle.raw() as usize, 0, 0],
FileSize { handle } => [op::FILE_SIZE, handle.raw() as usize, 0, 0],
ListDir { path_len } => [op::LIST_DIR, path_len, 0, 0],
Create { path_len } => [op::CREATE, path_len, 0, 0],
Delete { path_len } => [op::DELETE, path_len, 0, 0],
Mkdir { path_len } => [op::MKDIR, path_len, 0, 0],
SetLog => [op::SET_LOG, 0, 0, 0],
}
}
}
impl Decode for StorageRequest {
fn decode(w: [usize; 4]) -> Option<Self> {
use StorageRequest::*;
Some(match w[0] {
op::ATTACH => Attach,
op::OPEN => Open { path_len: w[1] },
op::READ => Read { handle: handle(w[1])?, len: w[2] },
op::WRITE => Write { handle: handle(w[1])?, len: w[2] },
op::CLOSE => Close { handle: handle(w[1])? },
op::FILE_SIZE => FileSize { handle: handle(w[1])? },
op::LIST_DIR => ListDir { path_len: w[1] },
op::CREATE => Create { path_len: w[1] },
op::DELETE => Delete { path_len: w[1] },
op::MKDIR => Mkdir { path_len: w[1] },
op::SET_LOG => SetLog,
_ => return None,
})
}
}
impl Encode for StorageResponse {
fn encode(&self) -> [usize; 4] {
use StorageResponse::*;
match *self {
Attached { size } => [reply::ATTACHED, size, 0, 0],
Handle(h) => [reply::HANDLE, h.raw() as usize, 0, 0],
Data { bytes } => [reply::DATA, bytes, 0, 0],
Written { bytes } => [reply::WRITTEN, bytes, 0, 0],
Ok => [reply::OK, 0, 0, 0],
DirEntries { count } => [reply::DIR_ENTRIES, count, 0, 0],
Size(s) => [reply::SIZE, s, 0, 0],
NotFound => [reply::NOT_FOUND, 0, 0, 0],
Error => [reply::ERROR, 0, 0, 0],
ReadOnly => [reply::READ_ONLY, 0, 0, 0],
NotAttached => [reply::NOT_ATTACHED, 0, 0, 0],
}
}
}
impl Decode for StorageResponse {
fn decode(w: [usize; 4]) -> Option<Self> {
use StorageResponse::*;
Some(match w[0] {
reply::ATTACHED => Attached { size: w[1] },
reply::HANDLE => Handle(handle(w[1])?),
reply::DATA => Data { bytes: w[1] },
reply::WRITTEN => Written { bytes: w[1] },
reply::OK => Ok,
reply::DIR_ENTRIES => DirEntries { count: w[1] },
reply::SIZE => Size(w[1]),
reply::NOT_FOUND => NotFound,
reply::ERROR => Error,
reply::READ_ONLY => ReadOnly,
reply::NOT_ATTACHED => NotAttached,
_ => return None,
})
}
}