diff --git a/src/backend.rs b/src/backend.rs index d085146b483..bcc2f2a41f3 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -9,12 +9,18 @@ //! Backends can also implement API extensions to provide additional syscalls (see the //! [`serde_extensions`][`crate::serde_extensions`] module). +use littlefs2::consts::PATH_MAX_PLUS_ONE; + use crate::{ api::{Reply, Request}, - error::Error, + error::{Error, Result}, platform::Platform, service::ServiceResources, - types::{Context, CoreContext}, + store::{ + certstore::ClientCertstore, counterstore::ClientCounterstore, filestore::ClientFilestore, + keystore::ClientKeystore, + }, + types::{Context, CoreContext, PathBuf}, }; /// The ID of a backend. @@ -91,3 +97,70 @@ impl TryFrom for NoId { Err(Error::InternalError) } } + +/// Global and per-client resources for a backend. +/// +/// This struct provides access to the store implementations for a backend, similar to +/// [`ServiceResources`][]. It adds the backend ID to all paths so that the global stores are +/// located at `backend-/` and the client stores are located at +/// `/backend-/`. +pub struct BackendResources<'a, P: Platform> { + resources: &'a mut ServiceResources

, + global_ctx: CoreContext, +} + +impl<'a, P: Platform> BackendResources<'a, P> { + pub fn new(resources: &'a mut ServiceResources

, id: &str) -> Self { + const PREFIX: &[u8] = "backend-".as_bytes(); + + let id = id.as_bytes(); + let n = PREFIX.len(); + let m = id.len(); + let mut path = [0; PATH_MAX_PLUS_ONE]; + path[..n].copy_from_slice(PREFIX); + path[n..n + m].copy_from_slice(id); + + Self { + resources, + global_ctx: CoreContext::new(PathBuf::from(&path[..n + m])), + } + } + + pub fn global_certstore(&mut self) -> Result> { + self.resources.certstore(&self.global_ctx) + } + + pub fn global_counterstore(&mut self) -> Result> { + self.resources.counterstore(&self.global_ctx) + } + + pub fn global_filestore(&mut self) -> ClientFilestore { + self.resources.filestore(&self.global_ctx) + } + + pub fn global_keystore(&mut self) -> Result> { + self.resources.keystore(&self.global_ctx) + } + + fn client_ctx(&self, ctx: &CoreContext) -> CoreContext { + let mut path = ctx.path.clone(); + path.push(&self.global_ctx.path); + CoreContext::new(path) + } + + pub fn client_certstore(&mut self, ctx: &CoreContext) -> Result> { + self.resources.certstore(&self.client_ctx(ctx)) + } + + pub fn client_counterstore(&mut self, ctx: &CoreContext) -> Result> { + self.resources.counterstore(&self.client_ctx(ctx)) + } + + pub fn client_filestore(&mut self, ctx: &CoreContext) -> ClientFilestore { + self.resources.filestore(&self.client_ctx(ctx)) + } + + pub fn client_keystore(&mut self, ctx: &CoreContext) -> Result> { + self.resources.keystore(&self.client_ctx(ctx)) + } +} diff --git a/src/service.rs b/src/service.rs index 16831f1f8e1..813682a8ff8 100644 --- a/src/service.rs +++ b/src/service.rs @@ -3,7 +3,7 @@ use rand_chacha::ChaCha8Rng; pub use rand_core::{RngCore, SeedableRng}; use crate::api::*; -use crate::backend::{BackendId, CoreOnly, Dispatch}; +use crate::backend::{BackendId, BackendResources, CoreOnly, Dispatch}; use crate::client::{ClientBuilder, ClientImplementation}; use crate::config::*; use crate::error::{Error, Result}; @@ -91,6 +91,10 @@ where unsafe impl Send for Service {} impl ServiceResources

{ + pub fn backend<'a>(&'a mut self, id: &str) -> BackendResources<'a, P> { + BackendResources::new(self, id) + } + pub fn certstore(&mut self, ctx: &CoreContext) -> Result> { self.rng() .map(|rng| ClientCertstore::new(ctx.path.clone(), rng, self.platform.store()))